synchronized 使用 优化 原理 |
您所在的位置:网站首页 › 偏向锁lock record › synchronized 使用 优化 原理 |
一、使用:
//
// 1 静态方法上加synchronized 锁对象是class文件
public static synchronized void test1() {
System.out.println("使用静态方法加锁。。");
}
// 2 普通方法上加synchronized 锁对象是this对象(注意如果对象不是单例,加锁没有意义)
public synchronized void test2() {
System.out.println("使用普通方法加锁。。");
}
// 3 普通方法内加synchronized 锁对象是this对象(注意如果对象不是单例,加锁没有意义)
public void test3() {
synchronized (Object.class) {
System.out.println("方法内部加锁。。");
}
}
二、优化:
2.1:锁粗化:
例如: StringBuffer sb = new StringBuffer(); public void test1() { sb.append(1); sb.append(2); sb.append(3); sb.append(4); } // append 方法源码如下 public synchronized StringBuffer append(int i) { toStringCache = null; super.append(i); return this; }test1方法 有4次加锁解锁,加锁解锁非常消耗性能, 所以从 java 1.6 以后,上面的test1方法不在是4次加锁解锁,而是优化一次加锁解锁,append方法的锁消除掉,逻辑如下: public void test1() { synchronized (Object.class) { sb.append(1); // append方法的synchronized锁消除掉 sb.append(2); sb.append(3); sb.append(4); } } 2.2:锁消除:例如: public Integer test() { synchronized (new Object()) { int a = 1; System.out.println("锁消除代码"); return a; } }锁对象不一致,加锁无意义,所以jvm 会去掉synchronized 锁, java 1.6 以后这个优化叫做锁消除 2.3:锁膨胀升级: java 1.6 后 ,做了优化,底层不在直接使用monitor重量级锁。下面讲原理会分析整个过程(这里只是图片,在下面第三块会分析整个流程)。
翻译成命令后 变成 public Integer test() { monitorEnter int a = 1; System.out.println("代码"); return a; monitorExit }当一个线程执行到monitorEnter命令时 , 尝试去抢占对象锁,如果锁已经被占用,那么线程进入等待队列。如果成功获取到锁,那么执行代码逻辑直到执行命令monitorExit,当前线程退出锁,通知其他等待线程竞争锁。 3.2 对象是怎么加锁的呢? 锁状态是被记录在每个对象的对象头(Mark Word)中,下面我们一 起认识一下对象的内存布局:
无锁:synchronized加锁的代码还没被线程执行过。 mark word数据如下 偏向锁:一旦有线程访问执行synchronized加锁的代码,立马升级为偏向锁, mark word:修改为 重量级锁:当多线程竞争很激烈,自旋等待失败后,升级位重量级锁。,mark word 如下 1、 所有new 出来的对象是否都存在堆区? 答案:否,因为如果jvm逃逸分析,一部分对象会存在栈区。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |